package com.itheimaoa.service.base.impl;

import java.io.Serializable;
import java.lang.reflect.ParameterizedType;
import java.sql.SQLException;
import java.util.Collection;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;

import javax.annotation.Resource;

import org.hibernate.HibernateException;
import org.hibernate.Query;
import org.hibernate.Session;
import org.springframework.orm.hibernate3.HibernateCallback;
import org.springframework.orm.hibernate3.HibernateTemplate;

import com.itheimaoa.domain.QueryResult;
import com.itheimaoa.service.base.ICommonService;

public abstract class CommonServiceImpl<T> implements ICommonService<T> {

	@Resource(name = "hibernateTemplate")
	public HibernateTemplate hibernateTemplate;
	protected Class<?> clazz;

	public CommonServiceImpl() {
		ParameterizedType type = (ParameterizedType) this.getClass().getGenericSuperclass();
		this.clazz = (Class<?>) type.getActualTypeArguments()[0];
		type.getRawType();
	}

	@Override
	public void saveEntity(T t) {
		this.hibernateTemplate.save(t);

	}

	@Override
	public void deleteEntity(Serializable id) {
		T t = this.findEntity(id);
		this.hibernateTemplate.delete(t);

	}

	@Override
	public void updateEntity(T t) {
		this.hibernateTemplate.update(t);
	}

	@SuppressWarnings("unchecked")
	@Override
	public T findEntity(Serializable id) {
		return (T) this.hibernateTemplate.get(this.clazz, id);
	}

	@SuppressWarnings("unchecked")
	@Override
	public Collection<T> getEntitys() {
		return this.hibernateTemplate.find(" from " + this.clazz.getName() + " o");
	}

	@SuppressWarnings("unchecked")
	@Override
	public QueryResult<T> getQueryResult(final Integer firstResult, final Integer maxResult, String strWhere, Object[] params, LinkedHashMap<String, String> orderby) {
		String jqpl = " from " + this.clazz.getSimpleName() + " o" + (strWhere != null && !"".equals(strWhere) ? " where " + strWhere : "");
		final String resultJpql = jqpl + orderByCondition(orderby);
		final String totalResultJpql = "select count(o) from " + this.clazz.getSimpleName() + " o" + (strWhere != null && !"".equals(strWhere) ? " where " + strWhere : "");
		return (QueryResult<T>) this.hibernateTemplate.execute(new HibernateCallback() {
			@Override
			public Object doInHibernate(Session session) throws HibernateException, SQLException {
				QueryResult<T> qr = new QueryResult<T>();
				Query query = session.createQuery(resultJpql);
				query.setFirstResult(firstResult).setMaxResults(maxResult);
				Long totalResult = (Long) session.createQuery(totalResultJpql).uniqueResult();
				List<T> list = query.list();
				qr.setResult(list);
				qr.setTotalResult(totalResult);
				return qr;
			}
		});
	}

	private String orderByCondition(LinkedHashMap<String, String> orderby) {
		StringBuffer buffer = new StringBuffer("");
		if (orderby != null) {
			buffer.append(" order by ");
			for (Map.Entry<String, String> map : orderby.entrySet()) {
				buffer.append(" " + map.getKey() + " " + map.getValue() + ",");
			}
			buffer.deleteCharAt(buffer.length() - 1);
		}
		return buffer.toString();
	}

}
